home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 3
/
Info_Mac_1994-01.iso
/
Graphics
/
Utility
/
GL Viewer 1.1.1
/
src ƒ
/
readfiles.c
< prev
next >
Wrap
Text File
|
1993-09-06
|
36KB
|
1,582 lines
/*
* Mac hack of
* readfiles.c - routines to load images, fonts, and execution files.
*
* Copyright (c) 1991 by Patrick J. Naughton
*/
#pragma segment Readfiles
#include "glassert.h"
#include "grasp.h"
#include "procImage.h"
#include "exec.h"
#include "fades.h"
ImageStruct *image[MAXIMAGES];
int numimages = 0;
FontStruct *font[MAXFONTS];
int numfonts = 0;
ExecStruct *execRec[MAXEXECS];
int numexecs = 0;
extern ImageStruct *readgifimage();
extern void exitcheck (void);
void
lowerstr(s)
char *s;
{
while (*s)
{
if (*s >= 'A' && *s <= 'Z')
*s += 'a' - 'A';
s++;
}
}
void
hexdump(fp, n)
FILE *fp;
int n;
{
long ofs = ftell(fp);
int i, j;
u_char b[16];
for (j = 0; j < n; j++) {
for (i = 0; i < 16; i++) {
b[i] = GetByte(fp);
fprintf(stderr,"%02x ", b[i]);
}
fprintf(stderr," ");
for (i = 0; i < 16; i++)
fprintf(stderr,"%c ", isprint(b[i]) ? b[i] : '.');
fprintf(stderr,"\n");
}
fseek(fp, ofs, 0);
}
/*-
Border Color Table
Color Color Palette 1 2 3
----- ----- ------- -----------------------------------
0 Black 0 Green Red Brown
1 Blue 1 Cyan Magenta White
2 Green 2 Cyan Red White
3 Cyan 3 Bright Green Bright Red Yellow
4 Red 4 Bright Cyan Bright Magenta White
5 Magenta 5 Bright Cyan Bright Red White
6 Brown -------------------------------------------
7 Grey
8 Dark Grey (Bright Black)
9 Bright Blue
10 Bright Green
11 Bright Cyan
12 Bright Red
13 Bright Magenta
14 Yellow (Bright Brown)
15 White (Bright Grey)
*/
u_short egapal[16][3] = {
{0x0000, 0x0000, 0x0000}, {0x0000, 0x0000, 0xaaaa},
{0x0000, 0xaaaa, 0x0000}, {0x0000, 0xaaaa, 0xaaaa},
{0xaaaa, 0x0000, 0x0000}, {0xaaaa, 0x0000, 0xaaaa},
{0xaaaa, 0x5555, 0x0000}, {0xaaaa, 0xaaaa, 0xaaaa},
{0x5555, 0x5555, 0x5555}, {0x5555, 0x5555, 0xffff},
{0x5555, 0xffff, 0x5555}, {0x5555, 0xffff, 0xffff},
{0xffff, 0x5555, 0x5555}, {0xffff, 0x5555, 0xffff},
{0xffff, 0xffff, 0x5555}, {0xffff, 0xffff, 0xffff}
};
int cgapal[3][6] = {
{2, 3, 3, 10, 11, 11},
{4, 5, 4, 12, 13, 12},
{6, 15, 15, 14, 15, 15}
};
Colormap CreateEGAcmap()
{
Colormap cmap;
XColor colors[16];
unsigned long pixels[16];
unsigned long pmasks;
int i;
cmap = XCreateColormap(dsp, win, vis, AllocNone);
XAllocColorCells(dsp, cmap, True, &pmasks, 0, pixels, 16);
for (i = 0; i < 16; i++) {
colors[i].pixel = pixels[i];
colors[i].red = egapal[i][0];
colors[i].green = egapal[i][1];
colors[i].blue = egapal[i][2];
colors[i].flags = DoRed | DoGreen | DoBlue;
}
XStoreColors(dsp, cmap, colors, 16);
return cmap;
}
int
findext(s)
char *s;
{
int i;
static char *exts[] = {
"pic", "pcx", "pal", "clp", "gif", "set", "fnt", "txt"
};
static int extcodes[] = {
EXT_PIC, EXT_PCX, EXT_PAL, EXT_CLP, EXT_GIF, EXT_SET, EXT_FNT, EXT_TXT
};
++s; /* get past the dot */
for (i = 0; i < (sizeof exts / sizeof exts[0]); i++)
if (!strcmp(s, exts[i]))
return extcodes[i];
return -1;
}
void
stringtofont(ex, i)
ExecStruct *ex;
{
int k;
char *s = strtok(ex->Code[i].val.s, ".");
lowerstr(s);
for (k = 0; k < numfonts; k++) {
if (!strcmp(font[k]->name, s)) {
free(ex->Code[i].val.s);
ex->Code[i].token = FONTTYPE;
ex->Code[i].val.font = font[k];
break;
}
}
if (k == numfonts) {
fprintf(stderr,"font \"%s\" referenced but not in directory.\n", s);
ex->Code[i].token = FONTTYPE;
ex->Code[i].val.font = 0;
}
}
void
stringtoimage(ex, i, deftype)
ExecStruct *ex;
int i;
int deftype;
{
int k;
char *s = strtok(ex->Code[i].val.s, ".");
char *ext = strrchr(ex->Code[i].val.s, '.');
if (ext) {
int extcode = findext(ext);
for (k = 0; k < numimages; k++) {
if (!strcmp(image[k]->name, s) && image[k]->type == extcode) {
free(ex->Code[i].val.s);
ex->Code[i].token = IMAGE;
ex->Code[i].val.image = image[k];
break;
}
}
} else {
for (k = 0; k < numimages; k++) {
if (!strcmp(image[k]->name, s)) {
/*
* this might be the second time through here, so don't free
* the string more than once...
*/
if (ex->Code[i].token == STRING) {
free(ex->Code[i].val.s);
ex->Code[i].token = IMAGE;
}
ex->Code[i].val.image = image[k];
if (image[k]->type == deftype)
break;
}
}
}
if (ex->Code[i].token != IMAGE)
error("%s: image \"%s\" referenced but not in directory.\n", s);
}
void
stringtolabel(ex, i)
ExecStruct *ex;
int i;
{
int k;
char *s = strtok(ex->Code[i].val.s, ".");
lowerstr(s);
for (k = 0; k < ex->numlabels; k++) {
if (!strcmp(s, ex->label[k].string)) {
free(ex->Code[i].val.s);
ex->Code[i].token = INTEGER;
ex->Code[i].val.i = ex->label[k].ipaddr;
break;
}
if (k == ex->numlabels)
error("%s: label \"%s\" referenced but not found.\n", s);
}
}
void
stringtoexec(ex, i)
ExecStruct *ex;
int i;
{
int k;
char *s = strtok(ex->Code[i].val.s, ".");
lowerstr(s);
for (k = 0; k < numexecs; k++) {
if (!strcmp(execRec[k]->name, s)) {
free(ex->Code[i].val.s);
ex->Code[i].token = EXECTYPE;
ex->Code[i].val.exec = execRec[k];
break;
}
}
if (k == numexecs)
error("%s: exec \"%s\" referenced but not in directory.\n", s);
}
int
calcwidth(data, width, height, left)
u_char *data;
int width;
int height;
int *left;
{
int bpsl = (width + 7) >> 3;
int right;
int mask;
int i;
int j;
/*find left */
*left = 0;
for (i = 0; i < bpsl; i++) {
for (mask = 0x80; mask > 0; mask >>= 1) {
for (j = 0; j < height; j++) {
if (data[j * bpsl + i] & mask)
goto calcright;
}
(*left)++;
}
}
*left = 0;
return width / 2; /* must be the space char... */
calcright:/* find right */
right = bpsl * 8;
for (i = bpsl - 1; i >= 0; i--) {
for (mask = 0x01; mask < 0x100; mask <<= 1) {
for (j = 0; j < height; j++) {
if (data[j * bpsl + i] & mask)
return right - *left;
}
right--;
}
}
error("%s: bad width calc.", NULL);
}
FontStruct *
readfont(fp, dirent)
FILE *fp;
FilenameStruct *dirent;
{
FontStruct *font;
XImage xim;
int first;
int num;
u_long datasize;
int i;
char *data;
fseek(fp, dirent->offset, 0);
font = (FontStruct *) malloc((size_t) sizeof(FontStruct));
assert (font);
font->name = strtok(strdup(dirent->fname), ".");
(void) GetLong(fp); /* skip file length */
(void) GetWord(fp); /* skip length */
if (imverbose)
hexdump(fp, 4);
num = GetByte(fp);
/* hack for trashed fonts... */
if (num == -1) {
free(font->name);
free((char *) font);
return (FontStruct *) 0;
}
first = GetByte(fp);
font->width = GetByte(fp);
font->height = GetByte(fp);
datasize = GetByte(fp);
data = (char *) malloc(datasize);
if (!data)
error("%s: couldn't malloc glyph memory\n", NULL);
if (verbose)
fprintf(stderr, "%s: (FNT) %d %dx%d,%d(%d) glyphs, from %d to %d\n",
font->name, num, font->width, font->height,
datasize, font->height * ((font->width + 7) >> 3),
first, first + num - 1);
xim.height = font->height;
xim.width = font->width;
xim.depth = 1;
xim.xoffset = 0;
xim.format = XYBitmap;
xim.data = data;
xim.byte_order = MSBFirst;
xim.bitmap_unit = 8;
xim.bitmap_bit_order = MSBFirst;
xim.bitmap_pad = 8;
xim.bytes_per_line = (font->width + 7) / 8;
for (i = 0; i < 256; i++) {
if (i >= first && i < first + num) {
fread(data, datasize, 1, fp);
font->glyphs[i].width = calcwidth((u_char *) data, font->width, font->height,
&font->glyphs[i].lbearing);
font->glyphs[i].pix = XCreatePixmap(dsp, win,
font->width, font->height, 1);
XPutImage(dsp, font->glyphs[i].pix, gc1, &xim, 0, 0, 0, 0,
font->width, font->height);
} else {
font->glyphs[i].pix = (Pixmap) 0;
font->glyphs[i].width = 0;
font->glyphs[i].lbearing = 0;
}
}
free(data);
return font;
}
FontStruct *
readset(fp, dirent)
FILE *fp;
FilenameStruct *dirent;
{
FontStruct *font;
XImage xim;
int first;
int num;
u_long datasize;
int i;
char *data;
char fontname[14];
int type;
int checktype;
int fontascent;
int proportional;
int bpsl;
int lfgap;
int italics;
int fntinvert;
int fnthbold;
int fntvbold;
int fnthmag;
int fntvmag;
int fnthfract;
int fntvfract;
int fntdirection;
int fntrot90;
int fnthflip;
int fntvflip;
int fntcolor;
int fntsubtype;
char unused[18];
int dataofs;
int celloffs[256];
int cellwidth[256];
fseek(fp, dirent->offset, 0);
(void) GetLong(fp); /* skip file length */
if (imverbose)
hexdump(fp, 4);
/* non-compressed type = 0x10 or compressed type = 0x14 */
type = GetByte(fp);
if (type != 0x10 && type != 0x14)
return readfont(fp, dirent);
fread(fontname, 13, 1, fp);
fontname[13] = 0;
/* non-compressed font = 0xba, compressed font = 0xdc */
checktype = GetByte(fp);
font = (FontStruct *) malloc((size_t) sizeof(FontStruct));
assert (font);
font->name = strtok(strdup(dirent->fname), ".");
fontascent = GetByte(fp);
num = GetByte(fp);
/* limited to the lower 94 ASCII characters: 0x21 - 0x7E */
first = GetByte(fp) + 0x20;
proportional = GetByte(fp); /* 0 = non-proportional */
font->width = GetByte(fp);
font->height = GetByte(fp);
bpsl = GetByte(fp);
datasize = font->height * bpsl;
spacegap = GetByte(fp);
chargap = GetByte(fp);
lfgap = GetByte(fp);
(void) GetWord(fp); /* skip file length */
italics = GetByte(fp);
fntinvert = GetByte(fp); /* 0 = dont invert, 1 = invert */
fnthbold = GetByte(fp); /* number of overlapping bits horizontal */
fntvbold = GetByte(fp); /* number of overlapping bits vertical */
fnthmag = GetByte(fp); /* integral horizontal bit magnification */
fntvmag = GetByte(fp); /* integral vertical bit magnification */
fnthfract = GetByte(fp); /* fractional horizontal bit magnification */
fntvfract = GetByte(fp); /* fractional vertical bit magnification */
fntdirection = GetByte(fp); /* Print direction 0 = left to right, 1...3 =
* counterclock 1...3 */
fntrot90 = GetByte(fp); /* rotation 0 = up, 1...3 = counterclock 1...3 */
fnthflip = GetByte(fp); /* horizontal flip 0 = no, 1 = yes */
fntvflip = GetByte(fp); /* vertical flip 0 = no, 1 = yes */
fntcolor = GetByte(fp); /* color of font */
fntsubtype = GetByte(fp); /* subcategory type of this font */
fread(unused, 18, 1, fp);
if (verbose)
fprintf(stderr, "%s[%s]: (SET) %d %dx%d,%d %sglyphs, from %d to %d\n",
font->name, fontname, num, font->width, font->height, datasize,
proportional ? "var-" : "fixed-", first, first + num - 1);
if (type == 0x10) {
for (i = 0; i <= num; i++)
celloffs[i] = GetWord(fp);
if (proportional) {
for (i = 0; i <= num; i++)
cellwidth[i] = GetByte(fp);
}
dataofs = ftell(fp) - dirent->offset + 4;
data = (char *) malloc(datasize * num);
if (!data)
error("%s: couldn't malloc glyph memory\n", NULL);
fread(data, num, datasize, fp);
xim.width = font->width;
xim.height = font->height;
xim.depth = 1;
xim.xoffset = 0;
xim.format = XYBitmap;
xim.data = 0;
xim.byte_order = MSBFirst;
xim.bitmap_unit = 8;
xim.bitmap_bit_order = MSBFirst;
xim.bitmap_pad = 8;
xim.bytes_per_line = bpsl;
for (i = 0; i < 256; i++) {
font->glyphs[i].pix = (Pixmap) 0;
font->glyphs[i].width = 0;
font->glyphs[i].lbearing = 0;
}
for (i = 0; i <= num; i++) {
int j = first + i - 1;
font->glyphs[j].lbearing = 0;
font->glyphs[j].width = proportional ? cellwidth[i] : font->width;
font->glyphs[j].pix = XCreatePixmap(dsp, win,
font->glyphs[j].width, font->height, 1);
xim.data = &data[celloffs[i] - dataofs];
XPutImage(dsp, font->glyphs[j].pix, gc1, &xim, 0, 0, 0, 0,
font->glyphs[j].width, font->height);
}
free(data);
} else {
fprintf(stderr,"don't do compressed SET's yet.\n");
}
return font;
}
#define fixcolr(c) ((c * 255 / maxcolorval) << 8)
static void
CheckColorMap (ImageStruct *pIm, short maxcolorval)
{
if (pIm /* != (ImageStruct *) NULL */ && pIm->cmaplen /* > 0 */)
{
register short i;
char fIsNonZero = 0;
for (i = 0; i < pIm->cmaplen; i++)
{
short r = pIm->colors[i].red >> 8;
short g = pIm->colors[i].green >> 8;
short b = pIm->colors[i].blue >> 8;
fIsNonZero |= r | g | b;
}
if (!fIsNonZero)
{
for (i = 0; i < pIm->cmaplen; i++)
{
u_short theColor = fixcolr (i);
pIm->colors[i].red = theColor;
pIm->colors[i].green = theColor;
pIm->colors[i].blue = theColor;
}
}
}
}
ImageStruct *
readimage(fp, dirent, filetype)
FILE *fp;
FilenameStruct *dirent;
int filetype;
{
ImageStruct *im;
XImage *xim;
int i;
int j;
int format;
long bpsl;
int blocks;
u_long datasize;
long blockoffset;
u_char *ptr;
int bpp;
int planes;
u_long idx;
int magic;
int unknown;
int type;
int edesc;
int exsize;
short maxcolorval;
u_long pixels[256];
u_long pmasks;
u_long filelen;
char *pDupName;
char fIsScrnText = 0;
im = (ImageStruct *) malloc((size_t) sizeof(ImageStruct));
assert (im);
fseek(fp, dirent->offset, 0);
filelen = GetLong(fp); /* length of whole image file... */
if (imverbose)
hexdump(fp, 4);
pDupName = strdup(dirent->fname);
im->name = strtok(pDupName, ".");
im->type = filetype;
magic = GetWord(fp);
if (magic != 0x1234) { /* I'm guessing here */
im->w = GetWord(fp);
im->h = GetWord(fp);
fprintf(stderr,"\nstrange magic, maybe bad data\n");
fprintf(stderr,"%dx%d %d, %d, %d, %ld\n", im->w, im->h, im->w * im->h / 4,
magic - 6, ((im->w + 3) >> 2) * im->h, filelen - 6);
#if 0
return NULL;
#endif
/* found in magic.gl
"15934x16190 64492865, 15928, 64500960, 1044266552"
im->w im->h w*h/4 magic-6 (w+3)>>2)*h filelen-6
magic == im.w
*/
im->xoff = 0;
im->yoff = 0;
bpp = 1;
planes = 1;
type = 'a';
edesc = 1;
exsize = 0;
} else {
im->w = GetWord(fp);
im->h = GetWord(fp);
im->xoff = GetWord(fp);
im->yoff = GetWord(fp);
bpp = GetByte(fp);
planes = ((bpp & 0xf0) >> 4) + 1;
bpp &= 0x0f;
if (GetByte(fp) != 0xff)
error("%s: %s is corrupt\n", im->name);
type = GetByte(fp);
edesc = GetWord(fp);
exsize = GetWord(fp);
fIsScrnText = ('0' <= type && type <= '3');
}
if (bpp == 1 && planes == 1) {
im->d = 1;
format = XYBitmap;
bpsl = (im->w + 7) >> 3;
#if 0
XSetForeground(dsp, gc, whiteC);
XSetBackground(dsp, gc, blackC);
#else
XSetBlackAndWhite (dsp, win);
#endif
} else {
im->d = 8;
format = fIsScrnText ? TextImage : ZPixmap;
bpsl = im->w;
}
datasize = bpsl * im->h;
ptr = (u_char *) malloc(datasize);
if (!ptr)
error("%s: readimage: malloc failed on image data.\n", NULL);
if (verbose)
fprintf(stderr,
"%s: (PIC) %dx%dx%d(%1x:%1x) [%d,%d] sz=%ld t=%c edesc=%02x ext=%d\n",
im->name,
im->w,
im->h,
im->d,
bpp, planes,
im->xoff,
im->yoff,
datasize,
type,
edesc,
exsize);
if (edesc != 0)
im->cmap = XCreateColormap(dsp, win, vis, AllocNone);
switch (edesc) {
case 0:
im->cmaplen = 0;
im->cmap = (Colormap) 0;
break;
case 1:
im->cmaplen = 4;
break;
case 2:
im->cmaplen = 16;
maxcolorval = 15;
break;
case 3:
im->cmaplen = 16;
maxcolorval = 63;
break;
case 4:
im->cmaplen = 256;
maxcolorval = 63;
break;
case 5:
im->cmaplen = 16;
maxcolorval = 63;
break;
default:
error("%s: bad edesc: %d\n", (char *) edesc);
}
if (im->cmaplen > 0)
XAllocColorCells(dsp, im->cmap, True, (unsigned long *) &pmasks,
0, (unsigned long *) pixels, im->cmaplen);
switch (edesc) {
case 0:
break;
case 1:
{
char pal;
if (exsize != 2)
error("%s: unexpected esize: %d\n", (char *) exsize);
pal = GetByte(fp);
j = GetByte(fp);
i = 0;
im->colors[i].pixel = pixels[i];
im->colors[i].red = egapal[j][0];
im->colors[i].green = egapal[j][1];
im->colors[i].blue = egapal[j][2];
im->colors[i].flags = DoRed | DoGreen | DoBlue;
for (i = 1; i < im->cmaplen; i++) {
j = cgapal[i - 1][pal];
im->colors[i].pixel = pixels[i];
im->colors[i].red = egapal[j][0];
im->colors[i].green = egapal[j][1];
im->colors[i].blue = egapal[j][2];
im->colors[i].flags = DoRed | DoGreen | DoBlue;
}
}
break;
case 2:
case 3:
if (exsize != im->cmaplen)
error("%s: bad exsize: %d\n", (char *) exsize);
for (i = 0; i < im->cmaplen; i++) {
int pal = GetByte(fp);
im->colors[i].pixel = pixels[i];
im->colors[i].red = decodepal(pal, 0x20, 0x04) << 8;
im->colors[i].green = decodepal(pal, 0x10, 0x02) << 8;
im->colors[i].blue = decodepal(pal, 0x08, 0x01) << 8;
im->colors[i].flags = DoRed | DoGreen | DoBlue;
}
break;
case 4:
case 5:
{
if (exsize != 0 && exsize != im->cmaplen * 3)
fprintf(stderr,"bad exsize: %d\n", exsize);
for (i = 0; i < im->cmaplen; i++) {
unsigned short r,g,b;
im->colors[i].pixel = pixels[i];
im->colors[i].red = fixcolr(r=GetByte(fp));
im->colors[i].green = fixcolr(g=GetByte(fp));
im->colors[i].blue = fixcolr(b=GetByte(fp));
im->colors[i].flags = DoRed | DoGreen | DoBlue;
}
break;
}
}
if (edesc > 0)
{
CheckColorMap (im, maxcolorval);
if (verbose) {
fprintf(stderr,"%d colors\n", im->cmaplen);
/*----
for (i = 0; i < im->cmaplen; i++) {
fprintf(stderr,"%02x%02x%02x ",
im->colors[i].red >> 8,
im->colors[i].green >> 8,
im->colors[i].blue >> 8);
if (!((i + 1) % 8))
fprintf(stderr,"\n");
}
-----*/
}
XStoreColors(dsp, im->cmap, im->colors, im->cmaplen);
}
if (magic != 0x1234) { /* BSAVE */
fread(ptr, filelen - 6, 1, fp);
} else {
blocks = GetWord(fp);
if (blocks == 0) {
if (imverbose)
fprintf(stderr,"unpacked data\n");
fread(ptr, datasize, 1, fp);
} else {
if (imverbose) {
fprintf(stderr,"%d image blocks\n", blocks);
hexdump(fp, 4);
}
blockoffset = ftell(fp);
idx = 0;
for (i = 0; i < blocks; i++) {
u_char esc;
int rlebytes;
int bufsize;
fseek(fp, blockoffset, 0);
rlebytes = GetWord(fp);
bufsize = GetWord(fp);
esc = GetByte(fp);
blockoffset += rlebytes;
if (imverbose) {
fprintf(stderr,"block: %d (len = %d) (bufsize = %d) (esc = %d)\n",
i, rlebytes, bufsize, esc);
hexdump(fp, 4);
}
rlebytes -= 5;
while (rlebytes) {
u_char c = GetByte(fp);
rlebytes--;
if (c == esc) {
u_int count = GetByte(fp);
rlebytes--;
if (count == 0) {
count = GetWord(fp);
rlebytes -= 2;
}
c = GetByte(fp);
rlebytes--;
#if 1
if (idx + count > datasize) {
fprintf(stderr, "*");
goto bailimage;
}
#endif
memset(&ptr[idx], c, count);
idx += count;
} else {
#if 1
if (idx + 1 > datasize) {
fprintf(stderr, "*");
goto bailimage;
}
#endif
ptr[idx] = c;
idx++;
}
}
}
}
}
bailimage:
switch (bpp) {
case 1:
switch (planes) {
case 1:
{
ptr = processVideoC (ptr, &datasize, &bpsl, im);
if (FDoSmallVideoC ())
ptr = shrinkVideoC (ptr, &datasize, &bpsl, im);
break;
}
case 2:
case 3:
error("%s: %d plane decoding not implemented\n", (char *) planes);
break;
case 4:
{
u_char *dst;
u_char *src;
u_char *old;
u_long srcbpsl = (im->w + 7) >> 3;
u_long plane0 = srcbpsl * 0 * im->h;
u_long plane1 = srcbpsl * 1 * im->h;
u_long plane2 = srcbpsl * 2 * im->h;
u_long plane3 = srcbpsl * 3 * im->h;
src = old = ptr;
dst = ptr = (u_char *) malloc(datasize);
if (!dst)
error("%s: readimage:4: malloc failed on image data.\n", NULL);
for (j = 0; j < im->h; j++) {
int mask = 0x80;
u_long addr = (u_long) j * srcbpsl;
for (i = 0; i < im->w; i++, mask >>= 1) {
if (mask == 0) {
mask = 0x80;
addr++;
}
*dst++ = ((src[plane0 + addr] & mask) != 0) +
2 * ((src[plane1 + addr] & mask) != 0) +
4 * ((src[plane2 + addr] & mask) != 0) +
8 * ((src[plane3 + addr] & mask) != 0);
}
}
free((char *) old);
}
break;
}
break;
case 2:
switch (planes) {
case 1:
{
u_char *dst;
u_char *src;
u_char *old;
int rem;
src = old = ptr;
dst = ptr = (u_char *) malloc(datasize);
if (!dst)
error("%s: readimage:2: malloc failed on image data.\n", NULL);
rem = im->w & 3;
for (i = 0; i < im->h; i++) {
for (j = 0; j < im->w >> 2; j++) {
*dst++ = *src >> 6 & 3;
*dst++ = *src >> 4 & 3;
*dst++ = *src >> 2 & 3;
*dst++ = *src >> 0 & 3;
src++;
}
switch (rem) {
case 3:
dst[2] = *src >> 2 & 3;
case 2:
dst[1] = *src >> 4 & 3;
case 1:
dst[0] = *src >> 6 & 3;
src++;
dst += rem;
case 0:
break;
}
}
free((char *) old);
}
break;
default:
error("%s: %d plane decoding not implemented\n", (char *) planes);
break;
}
break;
case 4:
{
u_char *dst;
u_char *src;
u_char *old;
src = old = ptr;
dst = ptr = (u_char *) malloc(datasize);
if (!dst)
error("%s: readimage:4b: malloc failed on image data.\n", NULL);
for (i = 0; i < im->h; i++) {
for (j = 0; j < im->w / 2; j++) {
*dst++ = *src >> 4 & 0xf;
*dst++ = *src >> 0 & 0xf;
src++;
}
}
free((char *) old);
}
break;
case 8:
break;
}
/* invert the image top to bottom */
// is this where we mess up left edge -> right edge ??
{
u_char *buffer;
buffer = (u_char *) malloc(bpsl);
assert (buffer);
for (i = 0; i < im->h / 2; i++) {
memcpy(buffer, ptr + (im->h - i - 1) * bpsl, bpsl);
memcpy(ptr + (im->h - i - 1) * bpsl, ptr + i * bpsl, bpsl);
memcpy(ptr + i * bpsl, buffer, bpsl);
}
free((char *) buffer);
}
xim = XCreateImage(dsp, vis, im->d, format, 0, (char *) ptr, im->w, im->h, 8, bpsl);
//im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8);
//XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h);
//XSync(dsp, False);
// mac, non-X fix
im->w= xim->width; // patch in case CreateImage needed to change size
im->h= xim->height;
im->pix = (Pixmap) xim;
return im;
}
ImageStruct *
readpcximage(fp, dirent)
FILE *fp;
FilenameStruct *dirent;
{
ImageStruct *im;
XImage *xim;
u_long i;
u_char pcxhd[128];
int magic;
int version;
int encoded;
int bpp;
int xmin, ymin, xmax, ymax;
int planes;
u_long bpsl;
u_long datasize;
u_char *ptr;
int maxcolorval;
u_long pixels[256];
u_long pmasks;
u_long filelen;
int format;
char *pDupName;
im = (ImageStruct *) malloc((size_t) sizeof(ImageStruct));
assert (im);
fseek(fp, dirent->offset, 0);
filelen = GetLong(fp); /* length of whole image file... */
if (imverbose)
hexdump(fp, 4);
pDupName = strdup(dirent->fname);
im->name = strtok(pDupName, ".");
im->type = EXT_PCX;
fread(pcxhd, 128, 1, fp);
magic = pcxhd[0];
if (magic != 0x0a)
fprintf(stderr,"I don't think this is really a .pcx file!\n");
version = pcxhd[1];
encoded = pcxhd[2];
xmin = pcxhd[4] + (256 * pcxhd[5]);
ymin = pcxhd[6] + (256 * pcxhd[7]);
xmax = pcxhd[8] + (256 * pcxhd[9]);
ymax = pcxhd[10] + (256 * pcxhd[11]);
im->w = xmax - xmin + 1;
im->h = ymax - ymin + 1;
im->xoff = im->yoff = 0;
bpsl = pcxhd[66] + (256 * pcxhd[67]);
bpp = pcxhd[3];
planes = pcxhd[65];
if (bpp == 1 && planes == 1) {
im->d = 1;
format = XYBitmap;
#if 0
XSetForeground(dsp, gc, whiteC);
XSetBackground(dsp, gc, blackC);
#else
XSetBlackAndWhite (dsp, win);
#endif
} else {
im->d = 8;
format = ZPixmap;
bpsl = im->w;
}
datasize = bpsl * im->h;
ptr = (u_char *) malloc(datasize);
if (!ptr)
error("%s: readpcximage: malloc failed on image data.\n", NULL);
if (verbose)
fprintf(stderr,"%s: (PCX) %dx%dx%d(%1x:%1x) [%d,%d] sz=%ld ver=%d enc=%d\n",
im->name,
im->w,
im->h,
im->d,
bpp, planes,
im->xoff,
im->yoff,
datasize,
version,
encoded);
if (version != 0)
im->cmap = XCreateColormap(dsp, win, vis, AllocNone);
switch (version) {
case 0:
case 3:
im->cmaplen = 0;
im->cmap = (Colormap) 0;
break;
case 2:
im->cmaplen = 16;
maxcolorval = 255;
break;
case 5:
im->cmaplen = 256;
maxcolorval = 255;
break;
case 1:
case 4:
default:
error("%s: bad pcx version: %d\n", (char *) version);
}
if (im->cmaplen > 0)
XAllocColorCells(dsp, im->cmap, True, (unsigned long *) &pmasks,
0, (unsigned long *) pixels, im->cmaplen);
switch (version) {
case 0:
case 3:
break;
case 2: /* I'm guessing here! */
for (i = 0; i < im->cmaplen; i++) {
im->colors[i].pixel = pixels[i];
im->colors[i].red = pcxhd[16 + i + 0] << 8;
im->colors[i].green = pcxhd[16 + i + 1] << 8;
im->colors[i].blue = pcxhd[16 + i + 2] << 8;
im->colors[i].flags = DoRed | DoGreen | DoBlue;
}
break;
case 5:
fseek(fp, dirent->offset + filelen + 4 - 769, 0);
if (GetByte(fp) != 12)
fprintf(stderr,"I don't think this is a VGA palette.\n");
for (i = 0; i < im->cmaplen; i++) {
im->colors[i].pixel = pixels[i];
im->colors[i].red = GetByte(fp) << 8;
im->colors[i].green = GetByte(fp) << 8;
im->colors[i].blue = GetByte(fp) << 8;
im->colors[i].flags = DoRed | DoGreen | DoBlue;
}
fseek(fp, dirent->offset + 4 + 128, 0);
break;
}
if (version > 0)
{
CheckColorMap (im, maxcolorval);
if (imverbose) {
fprintf(stderr,"%d colors\n", im->cmaplen);
/*---
for (i = 0; i < im->cmaplen; i++) {
fprintf(stderr,"%02x%02x%02x ",
im->colors[i].red >> 8,
im->colors[i].green >> 8,
im->colors[i].blue >> 8);
if (!((i + 1) % 8))
fprintf(stderr,"\n");
}
---*/
}
XStoreColors(dsp, im->cmap, im->colors, im->cmaplen);
}
if (encoded) {
/*
* Goes like this: Read a byte. If the two high bits are set, then the
* low 6 bits contain a repeat count, and the byte to repeat is the
* next byte in the file. If the two high bits are not set, then this
* is the byte to write.
*/
i = 0;
while (i < datasize)
{
int byte = GetByte(fp);
if ((byte & 0xc0) == 0xc0)
{
int count = byte & 0x3f;
int value = GetByte(fp);
if (i + count > datasize)
count = datasize - i - 1; /* catch overflow */
memset (ptr + i, value, count);
i += count;
}
else
{
ptr[i++] = byte;
}
}
}
else
fread(ptr, datasize, 1, fp);
/*
* need to do planar -> chunky conversion here if we support > 1 plane pcx
* files.
*/
xim = XCreateImage(dsp, vis, im->d, format, 0, (char *) ptr, im->w, im->h, 8, bpsl);
/*****
im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8);
XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h);
XSync(dsp, False);
*****/
// mac, non-X fix
im->w= xim->width; // patch in case CreateImage needed to change size
im->h= xim->height;
im->pix = (Pixmap) xim;
return im;
}
void
printcodes(ex)
ExecStruct *ex;
{
int i;
for (i = 0; i < ex->numcodes; i++) {
fprintf(stderr,"%4d: ", i);
if (ex->Code[i].token < NTOKENS)
fprintf(stderr,"[TOK] %s (%d) (%d args)\n",
tokens[ex->Code[i].token], ex->Code[i].token,
ex->Code[i].val.i);
else {
switch (ex->Code[i].token) {
case INTEGER:
fprintf(stderr,"[INT] %d\n", ex->Code[i].val.i);
break;
case STRING:
fprintf(stderr,"[STR] \"%s\"\n", ex->Code[i].val.s);
break;
case IMAGE:
fprintf(stderr,"[IMG] \"%s\"\n", ex->Code[i].val.image->name);
break;
case FONTTYPE:
fprintf(stderr,"[FNT] \"%s\"\n", ex->Code[i].val.font->name);
break;
case EXECTYPE:
fprintf(stderr,"[EXC] \"%s\"\n", ex->Code[i].val.exec->name);
break;
case WILDTYPE:
fprintf(stderr,"[WLD] \"@\"\n");
break;
default:
error("%s: printcodes bogosity (%d)\n", (char *) ex->Code[i].token);
}
}
}
fprintf(stderr,"labels:\n");
for (i = 0; i < ex->numlabels; i++)
fprintf(stderr,"[LABEL] \"%s\" %d\n", ex->label[i].string, ex->label[i].ipaddr);
}
/* turn all cload and pload args into pointers to the
* actual image structure instead of the filename
* turn all fload args into pointers to the font structure
* instead of the filename, and change the '@' string to a WILDTYPE.
*/
void
converttypes(ex)
ExecStruct *ex;
{
int i, j;
for (i = 0; i < ex->numcodes; i++) {
int t = ex->Code[i].token;
char *s = ex->Code[i].val.s;
char nargs = ex->Code[i].val.i;
switch (t) {
case STRING:
if (s[0] == '@' && s[1] == 0) {
ex->Code[i].token = WILDTYPE;
ex->Code[i].val.i = 0;
}
break;
case FLOAD:
stringtofont(ex, i + 1);
break;
case CLOAD:
stringtoimage(ex, i + 1, EXT_CLP);
break;
case PLOAD:
stringtoimage(ex, i + 1, EXT_PIC);
break;
case LINK:
case CALL:
stringtoexec(ex, i + 1);
if (nargs > 1)
stringtolabel(ex, i + 2);
break;
case DATABEGIN:
case GOTO:
case GOSUB:
stringtolabel(ex, i + 1);
break;
case IFKEY:
for (j = 2; j <= nargs; j += 2)
stringtolabel(ex, i + j);
break;
case IFMEM:
case IFVIDEO:
case WAITKEY:
if (nargs > 1)
stringtolabel(ex, i + 2);
break;
}
}
}
ExecStruct *
readtxt(fp, dir)
FILE *fp;
FilenameStruct *dir;
{
ExecStruct *ex;
u_long len;
char *txt;
int i;
ex = (ExecStruct *) calloc ((size_t) 1, (size_t) sizeof (ExecStruct));
assert (ex);
ex->name = strtok(strdup(dir->fname), ".");
fseek(fp, dir->offset, 0);
len = GetLong(fp);
len &= 0x00ffffff; /* hack */
ex->txt = (char *) malloc(len + 1);
assert (ex->txt);
fread(ex->txt, len, 1, fp);
ex->txt[len] = 26;
if (showtext)
puts(ex->txt);
return ex;
}
#define ADDIMAGE(im) \
{ \
if (im == (ImageStruct *) NULL && \
numimages /* > 0 */) \
{ \
fprintf (stderr, \
"readfiles () skipped bad image (%d). :-(\n", \
i); \
im = image[numimages - 1]; /* kluge */ \
} \
\
if (im /* != (ImageStruct *) NULL */) \
image[numimages++] = im; \
}
void
readfiles(fp, dir, count)
FILE *fp;
FilenameStruct *dir;
int count;
{
int i;
ImageStruct *im;
for (i = 0; i < count; i++)
{
char *p = strrchr(dir[i].fname, '.');
int extcode;
if (!p)
error("%s: %s has no extension.\n", dir[i].fname);
exitcheck ();
extcode = findext(p);
switch (extcode) {
case EXT_PCX:
im = readpcximage(fp, &dir[i]);
ADDIMAGE (im);
break;
case EXT_PIC:
case EXT_CLP:
case EXT_PAL:
im = readimage(fp, &dir[i], extcode);
ADDIMAGE (im);
break;
case EXT_GIF:
im = readgifimage (fp, &dir[i]);
ADDIMAGE (im);
break;
case EXT_SET:
font[numfonts++] = readset(fp, &dir[i]);
if (font[numfonts - 1] == (FontStruct *) 0)
--numfonts;
break;
case EXT_FNT:
font[numfonts++] = readfont(fp, &dir[i]);
if (font[numfonts - 1] == (FontStruct *) 0)
--numfonts;
break;
case EXT_TXT:
execRec[numexecs++] = readtxt(fp, &dir[i]);
break;
default:
if (!fQuiet)
fprintf(stderr,"skipping %s: unknown extension.\n", dir[i].fname);
}
}
for (i = 0; i < numexecs; i++)
{
ExecStruct *ex = execRec[i];
exitcheck ();
parsefile(ex, ex->txt);
converttypes(ex);
if (printthecodes)
printcodes(ex);
}
if (imageloop)
{
short ithImage;
char fDidVideo1 = 0;
short wMax;
short hMax;
for (ithImage = 0; ithImage < numimages; ithImage++)
{
ImageStruct *pIm = image[ithImage];
XImage *pXim = (XImage *) pIm->pix;
if (pXim->format == TextImage)
{
if (!fDidVideo1)
{
setvideomode ('1');
fDidVideo1 = 1;
}
continue;
}
if (ithImage == 0)
{
picreg[1] = pIm;
picreg[2] = pIm;
wMax = pIm->w;
hMax = pIm->h;
}
else
{
if (pIm->w > picreg[1]->w)
{
picreg[1] = pIm;
wMax = pIm->w;
}
else if (pIm->h > picreg[2]->h)
{
picreg[2] = pIm;
hMax = pIm->h;
}
}
}
if (!fDidVideo1 || picreg[0]->w != wMax || picreg[0]->h != hMax)
setvideomode ('?');
InitCursor ();
MoveTo (9, 140); DrawString ("\pImage loop...");
MoveTo (9, 160); DrawString ("\p([Option] click or command-. to continue.)");
for (ithImage = -1; ;)
{
char fShowImage = 0;
int theChar;
SystemTask ();
if (StopKey ())
break;
if (MouseButton ())
{
if (optionKeyIsDown ())
ithImage--;
else if (cmdKeyIsDown ())
ithImage = 0;
else
ithImage++;
fShowImage = 1;
}
if (Keypress (&theChar))
{
fShowImage = 1;
switch (theChar)
{
case 0x01: /* home */
case 0x1E: /* up arrow */
ithImage = 0;
break;
case 0x04: /* end */
case 0x1F: /* down arrow */
ithImage = numimages - 1;
break;
case 0x1C: /* left arrow */
case 0x0B: /* page up */
ithImage--;
break;
case 0x1D: /* right arrow */
case 0x0C: /* page down */
ithImage++;
break;
default:
fShowImage = 0;
break;
}
}
if (fShowImage)
{
ImageStruct *pIm;
XImage *pXim;
if (ithImage >= numimages)
ithImage = 0;
else if (ithImage < 0)
ithImage = numimages - 1;
pIm = image[ithImage];
pXim = (XImage *) pIm->pix;
if (pIm->d == 1 || pXim->format == TextImage)
XSetBlackAndWhite (dsp, win);
else if (pIm->cmap /* != (Colormap) NULL */)
XSetWindowColormap (dsp, win, pIm->cmap);
if (pXim->format == TextImage)
imagefade (0, pIm, 0, 0, 0, 0);
else
XCopyArea (dsp, pIm->pix, win, gc, 0, 0, pIm->w, pIm->h, 0, 0);
}
}
}
}